package deadlock

import "fmt"
import "dumpwave"

func decode(
		instruction		chan uint32,
		//pc_command		chan int32,
		decodeAlu		chan DEAL,
		decodeCop0		chan DECO,
		decodeRegister	chan DERE,
		decodeDmux		chan DEDM,
		decodeMux		chan DEMU,
		decodePC		chan DEPC) {

	var (
		OpCode uint32
		rd uint32
		rt uint32
		rs uint32
		base uint32
		offset uint32
		instr_index uint32
		var_decode uint32
		stateNextDecode uint32
		stateDecode uint32
		cp0bds uint32
	)

	for{
		var_instruction :=<-instruction
		fmt.Printf("[DECODE] Instruction <-- YAM: 0x%x\n",var_instruction)
		if var_instruction == 0 { fmt.Println("[YAM] HALT");for {} }
		OpCode = var_instruction >>26 //recebe os bits de 31 a 26 (registrador opcode)
		stateDecode = stateNextDecode
		fmt.Println("[DECODE] stateDecode =",stateDecode)
		var_decode = YES
		switch OpCode {
			case SPECIAL:
				fmt.Println("[DECODE] tag SPECIAL")
				OpCode = (var_instruction & 0x3F)
				switch OpCode {
					case ADD:
						fmt.Println("[DECODE] tag ADD")
						rd = (var_instruction & 0xF800)>>11
						rt = (var_instruction & 0x1F0000)>>16
						rs = (var_instruction & 0x3E00000)>>21
						// status do decode
						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							//pc_command <- PC_NEXT
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
							fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)

							cp0bds = 0
								fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}
						//comando para o cp0
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
							fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						//comando pra alu
						decodeAlu <- DEAL{CMD: ADD, IMMEDIATE: 0}
							fmt.Println("[DECODE] ADD --> ALU")
						//comando e valores para registrador
						decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}
							fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD rs: 0x%x rt: 0x%x rd: 0x%x\n",rs,rt,rd)
						//comando para demux
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}
							fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD unit: ALU)")
						//comando para o mux
						decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
							fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD unit: ALU)")

					case SUB:
							fmt.Println("[DECODE] tag SUB")
						rd = (var_instruction & 0xF800)>>11
						rt = (var_instruction & 0x1F0000)>>16
						rs = (var_instruction & 0x3E00000)>>21
						// status do decode
						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
							fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)
							
							cp0bds = 0
								fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}
						//comando para o cp0
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
							fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						//comando pra alu
						decodeAlu <- DEAL{CMD: SUB, IMMEDIATE: 0}
							fmt.Println("[DECODE] SUB --> ALU")
						//comando e valores para registrador
						decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}
							fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD rs: 0x%x rt: 0x%x rd: 0x%x\n",rs,rt,rd)
						//comando para demux
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}
							fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD unit: ALU)")
						//comando para o mux
						decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
							fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD unit: ALU)")

					case AND:
							fmt.Println("[DECODE] tag AND")
						rd = (var_instruction & 0xF800)>>11
						rt = (var_instruction & 0x1F0000)>>16
						rs = (var_instruction & 0x3E00000)>>21
						// status do decode
						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
							fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)
							cp0bds = 0
								fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}
						//comando para o cp0
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
							fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						//comando pra alu
						decodeAlu <- DEAL{CMD: AND, IMMEDIATE: 0}
							fmt.Println("[DECODE] AND --> ALU")
						//comando e valores para registrador
						decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}
							fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD rs: 0x%x rt: 0x%x rd: 0x%x\n",rs,rt,rd)
						//comando para demux
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}
							fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD unit: ALU)")
						//comando para o mux
						decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
							fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD unit: ALU)")
				}

			case LW:
				fmt.Println("[DECODE] tag LW")
				offset = (var_instruction & 0xFFFF)
				rt = (var_instruction & 0x1F0000)>>16
				base = (var_instruction & 0x3E00000)>>21

				if var_decode == YES{
					stateNextDecode = STATE_OTHERS
					dumpwave.Wave(1,"req_ack_DEPC")		//dumpWave
					dumpwave.Wave(PC_NEXT,"cha_DEPC")	//dumpWave
					decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					dumpwave.Wave(0,"req_ack_DEPC")		//dumpWave
					fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)
					cp0bds = 0
					fmt.Println("[DECODE] stateDecode = YES")
				} else{
					cp0bds = 1
				}
				dumpwave.Wave(1,"req_ack_DECO")			//dumpWave
				dumpwave.Wave(WAIT_EXCEPTION,"cha_DECO")	//dumpWave
				decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
				dumpwave.Wave(0,"req_ack_DECO")			//dumpWave
				fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
				
				dumpwave.Wave(1,"req_ack_DECO")			//dumpWave
				dumpwave.Wave(LW,"cha_DEAL")			//dumpWave
				decodeAlu <- DEAL{CMD: LW, IMMEDIATE: offset}
				dumpwave.Wave(0,"req_ack_DECO")			//dumpWave
				fmt.Println("[DECODE] LW --> ALU")

				dumpwave.Wave(1,"req_ack_DERE")			//dumpWave
				dumpwave.Wave(RRS_RRT,"cha_DERE")		//dumpWave
				decodeRegister <- DERE{RF_COMMAND:RRS_WRT, RS:base, RT:rt, RD:offset}
				dumpwave.Wave(0,"req_ack_DERE")			//dumpWave
				
				fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_WRT rs: 0x%x rt: 0x%x rd: 0x%x\n",base,rt,offset)

				dumpwave.Wave(1,"req_ack_DEDM")			//dumpWave
				dumpwave.Wave(RRS_RRT,"cha_DEDM")		//dumpWave
				decodeDmux <- DEDM{DMUX_COMMAND:RRS_WRT, DMUX_UNIT:ALU}
				dumpwave.Wave(0,"req_ack_DEDM")			//dumpWave
				fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_WRT unit: ALU)")

				dumpwave.Wave(1,"req_ack_DEMU")			//dumpWave
				dumpwave.Wave(RRS_RRT,"cha_DEMU")		//dumpWave
				decodeMux <- DEMU{MUX_COMMAND:RRS_WRT, MUX_UNIT:ALU}
				dumpwave.Wave(0,"req_ack_DEMU")			//dumpWave
				
				fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_WRT unit: ALU)")
 
			case SW:
				fmt.Println("[DECODE] tag SW")
				offset = (var_instruction & 0xFFFF)
				rt = (var_instruction & 0x1F0000)>>16
				base = (var_instruction & 0x3E00000)>>21

				if var_decode == YES{
					stateNextDecode = STATE_OTHERS
					decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)
					cp0bds = 0
					fmt.Println("[DECODE] stateDecode = YES")
				} else{
					cp0bds = 1
				}
				
				decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
				fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")

				decodeAlu <- DEAL{CMD: SW, IMMEDIATE: offset}
				fmt.Println("[DECODE] SW --> ALU")

				decodeRegister <- DERE{RF_COMMAND:RRS_RRT, RS:base, RT:rt, RD:offset}
				fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT rs: 0x%x rt: 0x%x rd: 0x%x\n",base,rt,offset)

				decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT, DMUX_UNIT:ALU}
				fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT unit: ALU)")
				
			case J:
				fmt.Println("[DECODE] tag J")
				if var_decode == YES{
					fmt.Println("[DECODE] stateDecode = YES")
					stateNextDecode = STATE_NULLIFY_SECOND
					instr_index = (var_instruction & 0x3FFFFFF)
					offset = (var_instruction & 0xFF)
					
					decodePC <- DEPC{PC_COMMAND: PC_IMMEDIATE_JUMP, PC_IMMEDIATE: instr_index, PC_OFFSET: offset, PC_BUFFERS: 0}
					fmt.Printf("[DECODE] DEPC --> PC (command: PC_NEXT immediate: 0x%x offset: 0x%x buffers: 0)\n",instr_index,offset)
					
					decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 1}
					fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING)")
				}
			
			case BEQ:
				fmt.Println("[DECODE] tag BEQ")
				if var_decode == YES{
					offset = (var_instruction & 0xFF)
					rt = (var_instruction & 0x1F0000)>>16
					rs = (var_instruction & 0x3E00000)>>21

					fmt.Println("[DECODE] stateDecode = YES")
					stateNextDecode = STATE_BRANCH_SENT
					decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 1}
					
					decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: offset, PC_BUFFERS: 0}
					
					decodeRegister <- DERE{RF_COMMAND:RRS_RRT, RS:rs, RT:rt, RD:0}
					
					decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT, DMUX_UNIT:ALU}
					
					decodeAlu <-DEAL{CMD: BEQ, IMMEDIATE: 0}// RT: RS:}
				}
			}
		}
}